CropAndResize
从输入图像 Tensor 中提取指定区域的切片,并通过双线性插值调整到目标大小。
该算子根据一组归一化坐标框 boxes (格式为 [y1, x1, y2, x2]),从输入图像的对应区域中采样,插值输出到 output_shape 指定的尺寸。
坐标映射
对于第 \(b\) 个框,输出像素 \((h, w)\) 对应的输入浮点坐标 \((y, x)\) 为:
当 \(H_{out} = 1\) 时,\(y = 0.5 \cdot (y_1 + y_2) \cdot (H_{in} - 1)\);当 \(W_{out} = 1\) 时,\(x = 0.5 \cdot (x_1 + x_2) \cdot (W_{in} - 1)\)。
边界索引与权重
对浮点坐标 \(out\) 及输入尺寸 \(in\) ,计算整数边界和插值权重:
双线性插值
先在水平方向逐行插值,再在垂直方向插值:
外插值处理
当 \(y < 0\) 或 \(y > H_{in} - 1\),或 \(x < 0\) 或 \(x > W_{in} - 1\) 时,输出像素值取 extrapolation_value。
- 输入:
src - 输入数据的地址。
box_idx - boxes的索引,box_idx[i]的值表示第i个框的图像的值。
boxes - 第i行表示box_index[i]图像区域的坐标,并且坐标[y1,x1,y2,x2]是归一化后的值。归一化后的坐标值y,映射到图像y*(image_height-1)处,因此归一化后的图像高度范围为[0,1],映射到实际图像高度范围为[0,image_height-1]。我们允许y1>y2,在这种情况下,视为原始图像的上下翻转变换。宽度尺寸的处理类似。坐标取值允许在[0,1]范围之外,在这种情况下,我们使用extrapolation_value外插值进行补齐。
param - 算子计算所需参数的结构体。其各成员见下述。
extrapolation_value - 外插值。
core_mask - 核掩码(仅共享存储版本使用)。
CropAndResizeParameter定义:
1typedef struct CropAndResizeParameter {
2 int* input_shape_; // 输入张量形状,4个int,格式为[batch, height, width, channel]
3 int* output_shape_; // 输出张量形状,4个int,格式为[batch, height, width, channel]
4 int* x_lefts_; // 水平方向左边界索引,output_shape[2]个int
5 int* x_rights_; // 水平方向右边界索引,output_shape[2]个int
6 int* y_tops_; // 垂直方向上边界索引,output_shape[1]个int
7 int* y_bottoms_; // 垂直方向下边界索引,output_shape[1]个int
8 void* x_weights_; // 水平方向插值权重,output_shape[2]个float
9 void* y_weights_; // 垂直方向插值权重,output_shape[1]个float
10 void* line_buffers_; // 双线性插值中间行缓冲,2 * output_shape[2] * input_shape[3] * type_size 字节 * core_num
11} CropAndResizeParameter;
- 输出:
dst - 输出地址。
- 支持平台:
FT78NEMT7004
备注
FT78NE 支持 fp32。
MT7004 支持 fp16、fp32。
公式符号与输入参数对照:
公式符号 |
输入参数/含义 |
|---|---|
\(I\) |
|
\(O\) |
|
\(b\) |
框索引,由 |
\((y_1, x_1, y_2, x_2)\) |
|
\((H_{in}, W_{in}, C_{in})\) |
|
\((H_{out}, W_{out}, C_{out})\) |
|
\(y_{bottom}[h],\; y_{top}[h]\) |
|
\(x_{left}[w],\; x_{right}[w]\) |
|
\(w_{y\_bottom}[h]\) |
|
\(w_{x\_left}[w]\) |
|
\(\text{extrapolation_value}\) |
|
共享存储版本:
-
void fp_crop_and_resize_s(float *src, float *dst, int *box_idx, float *boxes, CropAndResizeParameter *param, float extrapolation_value, int core_mask)
-
void hp_crop_and_resize_s(float16 *src, float16 *dst, int *box_idx, float *boxes, CropAndResizeParameter *param, float16 extrapolation_value, int core_mask)
C调用示例:
1// MT7004 示例(共享存储多核,DDR 地址)
2void TestCropAndResizeSMCFp32(int* input_shape, int* output_shape, float* inp_boxes, int32_t* inp_box_idx, float extrapolation_value, int core_mask) {
3 int core_id = get_core_id();
4 int core_num = GetCoreNum(core_mask);
5 int logic_core_id = GetLogicCoreId(core_mask, core_id);
6 float* input = (float*)0x88000000;
7 float* output = (float*)0x89000000;
8 float* boxes = (float*)0x8A000000;
9 int* box_idx = (int*)0x8B000000;
10 CropAndResizeParameter* param = (CropAndResizeParameter*)0x8C000000;
11 if (logic_core_id == 0) {
12 memcpy(boxes, inp_boxes, sizeof(float) * output_shape[0] * 4);
13 memcpy(box_idx, inp_box_idx, sizeof(int) * output_shape[0]);
14 param->input_shape_ = (int*)0x8D000000;
15 memcpy(param->input_shape_, input_shape, sizeof(int) * 4);
16 param->output_shape_ = (int*)0x8E000000;
17 memcpy(param->output_shape_, output_shape, sizeof(int) * 4);
18 param->line_buffers_ = (void*)0x8F000000;
19 param->x_lefts_ = (int*)0x90000000;
20 param->x_rights_ = (int*)0x91000000;
21 param->y_bottoms_ = (int*)0x92000000;
22 param->y_tops_ = (int*)0x93000000;
23 param->x_weights_ = (void*)0x94000000;
24 param->y_weights_ = (void*)0x95000000;
25 PrepareCropAndResizeBilinear(param->input_shape_, boxes, param->output_shape_, param->y_bottoms_, param->y_tops_,
26 param->x_lefts_, param->x_rights_, param->y_weights_, param->x_weights_); // 做预处理
27 }
28 sys_bar(0, core_num); // 初始化参数完成后进行同步
29 fp_crop_and_resize_s(input, output, box_idx, boxes, param, extrapolation_value, core_mask);
30}
31
32void main(){
33 int input_shape[4] = {1, 4, 4, 4};
34 int output_shape[4] = {1, 8, 8, 4};
35 float boxes[4] = {0, 0, 0.5, 0.5};
36 int box_idx[1] = {0};
37 int core_mask = 0b1111;
38 float extrapolation_value = 0.5;
39 TestCropAndResizeSMCFp32(input_shape, output_shape, boxes, box_idx, extrapolation_value, core_mask);
40}
私有存储版本:
-
void fp_crop_and_resize_p(float *src, float *dst, int *box_idx, float *boxes, CropAndResizeParameter *param, float extrapolation_value)
-
void hp_crop_and_resize_p(float16 *src, float16 *dst, int *box_idx, float *boxes, CropAndResizeParameter *param, float16 extrapolation_value)
C调用示例:
1// MT7004 示例(私有存储单核,AM 地址)
2void TestCropAndResizeSMCFp32_p(int* input_shape, int* output_shape, float* inp_boxes, int32_t* inp_box_idx, float extrapolation_value) {
3 float* input = (float*)0x10000000;
4 float* output = (float*)0x10020000;
5 float* boxes = (float*)0x10040000;
6 int* box_idx = (int*)0x10060000;
7 CropAndResizeParameter* param = (CropAndResizeParameter*)0x10080000;
8
9 memcpy(boxes, inp_boxes, sizeof(float) * output_shape[0] * 4);
10 memcpy(box_idx, inp_box_idx, sizeof(int) * output_shape[0]);
11 param->input_shape_ = (int*)0x10090000;
12 memcpy(param->input_shape_, input_shape, sizeof(int) * 4);
13 param->output_shape_ = (int*)0x100A0000;
14 memcpy(param->output_shape_, output_shape, sizeof(int) * 4);
15 param->line_buffers_ = (void*)0x100B0000;
16 param->x_lefts_ = (int*)0x100C0000;
17 param->x_rights_ = (int*)0x100D0000;
18 param->y_bottoms_ = (int*)0x100E0000;
19 param->y_tops_ = (int*)0x100F0000;
20 param->x_weights_ = (void*)0x10100000;
21 param->y_weights_ = (void*)0x10110000;
22 PrepareCropAndResizeBilinear(param->input_shape_, boxes, param->output_shape_, param->y_bottoms_, param->y_tops_,
23 param->x_lefts_, param->x_rights_, param->y_weights_, param->x_weights_);
24
25 fp_crop_and_resize_p(input, output, box_idx, boxes, param, extrapolation_value);
26}
27
28void main(){
29 int input_shape[4] = {1, 4, 4, 4};
30 int output_shape[4] = {1, 8, 8, 4};
31 float boxes[4] = {0, 0, 0.5, 0.5};
32 int box_idx[1] = {0};
33 float extrapolation_value = 0.5;
34 TestCropAndResizeSMCFp32_p(input_shape, output_shape, boxes, box_idx, extrapolation_value);
35}